/**

 @Name：layui.atree2.0 树组件
 @Author：smallwei
 @License：MIT

 */

layui.define('jquery', function (exports) {
    "use strict";

    var $ = layui.$,
        hint = layui.hint();
    //勾选集合
    var changeList = [];
    //变量别名
    var props = {
        name: 'name',
        id: 'id',
        children: 'children',
        checkbox: 'checkbox',
        spread: 'spread',
        deleteBtnLabelKey: 'delete',
        addBtnLabelKey: 'add',
    };

    var enterSkin = 'layui-atree-enter',
        Atree = function (options) {
            //缓冲重要变量
            this.$vm = this;
            this.$options = options || {};
            this.$el = this.utils.isElementNode(this.$options.elem) ? this.$options.elem : $(this.$options.elem);

            //模块的属性
            this.nodes = this.$options.nodes || [];
            this.props = this.$options.props || props;

            //模块的别名
            this.nameKey = this.props.name || props.name;
            this.idKey = this.props.id || props.id;
            this.childrenKey = this.props.children || props.children;
            this.checkboxKey = this.props.checkbox || props.checkbox;
            this.spreadKey = this.props.spread || props.spread;
            this.addBtnLabelKey = this.props.addBtnLabel || props.addBtnLabel;
            this.deleteBtnLabelKey = this.props.deleteBtnLabel || props.deleteBtnLabel;
        };

    //图标
    var icon = {
        arrow: ['&#xe623;', '&#xe625;'] //箭头
        ,
        checkbox: ['&#xe68c;', '&#xe624;'] //复选框
        ,
        leaf: '&#xe621;' //叶节点
    };

    //工具包
    Atree.prototype.utils = (function () {
        return {
            isElementNode: function (node) {
                return node.nodeType === 1;
            }
        }
    })()

    //初始化
    Atree.prototype.init = function () {
        var that = this.$vm,
            options = this.$options
        that.$el.addClass('layui-box layui-atree'); //添加tree样式
        if (options.skin) {
            that.$el.addClass('layui-atree-skin-' + options.skin);
        }
        that.tree(that.$el, that.nodes);
        that.on(that.$el);
    };

    //树节点解析
    Atree.prototype.tree = function (elem, children, parent) {
        var that = this.$vm,
            options = this.$options
        var nodes = children;
        layui.each(nodes, function (index, item) {
            var hasChild = item[that.childrenKey] && item[that.childrenKey].length > 0;
            var dom = that.getDom(item);
            if (parent) item.$parent = parent;
            var ul = $(dom.ul(item));
            var li = $(that.getNode(item));

            //如果被选中加入checkbox集合里
            if (item[that.checkboxKey]) {
                changeList.push(item);
            }

            //如果有子节点，则递归继续生成树
            if (hasChild) {
                li.append(ul);
                that.tree(ul, item[that.childrenKey], item);
            }
            //伸展节点
            that.spread(li, item);
            that.bindUlEvent(li, item);
            elem.append(li);
        });
    };

    //节点dom拼接
    Atree.prototype.getDom = function (item) {
        var that = this.$vm,
            options = this.$options,
            item = item,
            hasChild = item[that.childrenKey] && item[that.childrenKey].length > 0;
        return {
            spread: function () {
                return hasChild ? '<i class="layui-icon layui-atree-spread">' + (
                    item[that.spreadKey] || options.spreadAll ? icon.arrow[1] : icon.arrow[0]
                ) + '</i>' : '';
            },
            checkbox: function () {
                return options.check ? (
                    '<i class="layui-icon layui-atree-check' + (item[that.checkboxKey] ? ' is-checked' : '') + '">' + (
                        item[that.checkboxKey] ? icon.checkbox[1] : icon.checkbox[0]
                    ) + '</i>'
                ) : '';
            },
            ul: function () {
                return '<ul class="' + (item[that.spreadKey] || options.spreadAll ? "layui-show" : "") + '"></ul>'
            },
            node: function () {
                return '<a href="' + (item.href || 'javascript:;') + '" ' + (
                    options.target && item.href ? 'target=\"' + options.target + '\"' : ''
                ) + '>' +
                    ('<cite>' + (item[that.nameKey] || '未命名') + '</cite></a>')
            },
            menu: function () {
                return '<div class="layui-atree-menu">' +
                    '<span class="layui-atree-add">' + that.addBtnLabelKey + '</span>' +
                    '<span class="layui-atree-delete">' + that.deleteBtnLabelKey + '</span>' +
                    '</div>'
            }
        }
    }
    //获取树节点
    Atree.prototype.getNode = function (item) {
        var that = this.$vm,
            options = this.$options
        var dom = that.getDom(item);
        var li = ['<li ' +
            (item[that.spreadKey] || options.spreadAll ? 'data-spread="' + (item[that.spreadKey] || true) + '"' : '') +
            (item[that.checkboxKey] ? 'data-check="' + item[that.checkboxKey] + '"' : '') +
            ('data-id=' + item[that.idKey]) +
            '><div class="layui-atree-node">'
            //展开箭头
            ,
        dom.spread()

            //复选框
            ,
        dom.checkbox()

            //节点
            ,
        dom.node()
            //菜单
            ,
        dom.menu(),
            '</div></li>'
        ].join('');
        return li;
    }

    //父绑定事件
    Atree.prototype.bindUlEvent = function (li, item) {
        var that = this.$vm,
            options = this.$options
        //触发点击节点回调
        typeof options.click === 'function' && that.click(li, item);

        //节点选择
        typeof options.change === 'function' && options.check === 'checkbox' && that.checkbox(li, item);

        //新增方法
        typeof options.addClick === 'function' && that.add(li, item);

        //删除方法
        typeof options.deleteClick === 'function' && that.delete(li, item);

        //拖拽节点
        options.drag && that.drag(li, item);
    }

    //选中回调函数
    Atree.prototype.change = function () {
        var that = this.$vm,
            options = this.$options;
        options.change(changeList);
    },

        //新增方法回调
        Atree.prototype.add = function (elem, item) {
            var that = this.$vm,
                options = this.$options;
            var node = elem.children('.layui-atree-node');
            var addBtn = node.children('.layui-atree-menu').children('.layui-atree-add')
            var arrow = node.children('.layui-atree-spread')
            var ul = elem.children('ul'),
                a = node.children('a');
            var addEvent = function (e) {
                layui.stope(e);
                var _addEvent = {
                    add: function (itemAddObj) {
                        if (!item[that.childrenKey]) {
                            item[that.childrenKey] = [];
                        }
                        item[that.childrenKey].push(itemAddObj);
                        var dom = that.getDom(item);
                        if (!ul[0]) {
                            ul = $(dom.ul())
                            elem.append(ul);
                        }
                        if (!arrow[0]) {
                            arrow = $(dom.spread());
                            node.prepend(arrow);
                            that.spread(elem, item);
                        }
                        if (!elem.data('spread')) {
                            that.open(elem, ul, arrow)
                        }
                        var li = $(that.getNode(itemAddObj));
                        that.bindUlEvent(li, itemAddObj);
                        ul.append(li);
                    }
                }
                options.addClick(item, elem, _addEvent.add)
            }
            addBtn.on('click', addEvent);
        }

    //删除方法回调
    Atree.prototype.delete = function (elem, item) {
        var that = this.$vm,
            options = this.$options;
        var node = elem.children('.layui-atree-node');
        var deleteBtn = node.children('.layui-atree-menu').children('.layui-atree-delete')
        var ul = elem.children('ul'),
            a = elem.children('a');
        var deleteEvent = function (e) {
            layui.stope(e);
            var _deleteEvent = {
                done: function () {
                    var parent = elem.parent();
                    var arrow = parent.parent().children('.layui-atree-spread')
                    if (parent.children('li').length === 1) {
                        arrow.remove();
                    }
                    elem.remove();
                }
            }
            options.deleteClick(item, elem, _deleteEvent.done)
        }
        deleteBtn.on('click', deleteEvent);
    }

    //点击节点回调
    Atree.prototype.click = function (elem, item) {
        var that = this.$vm,
            options = this.$options;
        var node = elem.children('.layui-atree-node');
        node.children('a').on('click', function (e) {
            layui.stope(e);
            options.click(item)
        });
    };

    //节点选择
    Atree.prototype.checkbox = function (elem, item) {
        var that = this.$vm,
            options = this.$options;
        var node = elem.children('.layui-atree-node');
        var checkbox = node.children('.layui-atree-check')
        var ul = elem.children('ul'),
            a = node.children('a');

        //递归设置子节点
        var setAllChildCheck = function (dom, item, type) {
            var list = dom.children('.layui-show').find('li');
            var children = item ? item.children || [] : [];
            for (var i = 0; i < list.length; i++) {
                var li = $(list[i]);
                setCheck(li, children[i], type);
                setAllChildCheck(li, children[i], type);
            }
        }

        //递归设置父节点
        var setAllPatentCheck = function (dom, item, type) {
            var parent = dom.parent().parent();
            var list = parent.children('.layui-show').find('li');
            var isChildrenCheck = true;
            for (var i = 0; i < list.length; i++) {
                var li = $(list[i]);
                if (!li.data('check')) isChildrenCheck = false;
            }
            if (item.$parent && (isChildrenCheck || !type)) {
                setCheck(parent, item.$parent, type);
                setAllPatentCheck(parent, item.$parent, type);
            }
        }

        //设置节点选中状态
        var setCheck = function (elem, item, type) {
            var checkbox = elem.children('.layui-atree-node').find('.layui-atree-check');
            if (type) {
                elem.data('check', true)
                elem.attr("data-check", true);
                checkbox.html(icon.checkbox[1])
                checkbox.addClass(' is-checked');
            } else {
                elem.data('check', null);
                elem.attr("data-check", null);
                checkbox.removeClass(' is-checked');
                checkbox.html(icon.checkbox[0])
            }
            if (item) {
                var index = layui.findObj(changeList, item[that.idKey], that.idKey);
                debugger
                if (index === -1 && type === true) {
                    changeList.push(item);
                } else if (type === false) {
                    changeList.splice(index, 1);
                }
            }
        }
        var check = function () {
            var checkFlag;
            if (elem.data('check')) {
                checkFlag = false;
            } else {
                checkFlag = true;
            }

            setCheck(elem, item, checkFlag)
            setAllPatentCheck(elem, item, checkFlag);
            setAllChildCheck(elem, item, checkFlag);

            that.change();
        }
        checkbox.on('click', check);
    };

    //伸展节点
    Atree.prototype.spread = function (elem, item) {
        var that = this.$vm,
            options = this.$options;
        var node = elem.children('.layui-atree-node');
        var arrow = node.children('.layui-atree-spread')
        var ul = elem.children('ul'),
            a = node.children('a');
        //如果没有子节点，则不执行
        if (!ul[0]) return;
        arrow.on('click', function () {
            that.open(elem, ul, arrow)
        });
    }

    //打开节点
    Atree.prototype.open = function (elem, ul, arrow) {
        if (elem.data('spread')) {
            elem.data('spread', null)
            elem.attr("data-spread", null);
            ul.removeClass('layui-show');
            arrow.html(icon.arrow[0]);
        } else {
            elem.data('spread', true);
            elem.attr("data-spread", true);
            ul.addClass('layui-show');
            arrow.html(icon.arrow[1]);
        }
    };
    //通用事件
    Atree.prototype.on = function (elem) {
        var that = this.$vm,
            options = this.$options;
        var dragStr = 'layui-atree-drag';

        //屏蔽选中文字
        elem.find('i').on('selectstart', function (e) {
            return false
        });

        //拖拽
        if (options.drag) {
            $(document).on('mousemove', function (e) {
                var move = that.move;
                if (move.from) {
                    var to = move.to,
                        treeMove = $('<div class="layui-box ' + dragStr + '"></div>');
                    e.preventDefault();
                    $('.' + dragStr)[0] || $('body').append(treeMove);
                    var dragElem = $('.' + dragStr)[0] ? $('.' + dragStr) : treeMove;
                    (dragElem).addClass('layui-show').html(move.from.elem.children('a').html());
                    dragElem.css({
                        left: e.pageX + 10,
                        top: e.pageY + 10
                    })
                }
            }).on('mouseup', function () {
                var move = that.move;
                if (move.from) {
                    move.from.elem.children('a').removeClass(enterSkin);
                    move.to && move.to.elem.children('a').removeClass(enterSkin);
                    that.move = {};
                    $('.' + dragStr).remove();
                }
            });
        }
    };

    //拖拽节点
    Atree.prototype.move = {};
    Atree.prototype.drag = function (elem, item) {
        var that = this.$vm,
            options = this.$options;
        var a = elem.children('a'),
            mouseenter = function () {
                var othis = $(this),
                    move = that.move;
                if (move.from) {
                    move.to = {
                        item: item,
                        elem: elem
                    };
                    othis.addClass(enterSkin);
                }
            };
        a.on('mousedown', function () {
            var move = that.move
            move.from = {
                item: item,
                elem: elem
            };
        });
        a.on('mouseenter', mouseenter).on('mousemove', mouseenter)
            .on('mouseleave', function () {
                var othis = $(this),
                    move = that.move;
                if (move.from) {
                    delete move.to;
                    othis.removeClass(enterSkin);
                }
            });
    };

    //暴露接口
    exports('atree', function (options) {
        var atree = new Atree(options = options || {});
        var elem = $(options.elem);
        if (!elem[0]) {
            return hint.error('layui.atree 没有找到' + options.elem + '元素');
        }
        atree.init(elem);
    });
});